#include "WorldApp.h"
#include "vect.h"
#include "quat.h"
#include "mat4.h"

// debug me beautiful
#include <iostream>
using namespace std;
////


WorldApp::WorldApp(World* w) {
	world = w;
	w->init();
	camera = new EntRenderer;
	world->getEntities()->add(camera);
}

void WorldApp::display() {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glEnable(GL_CULL_FACE);
	glEnable(GL_DEPTH_TEST);

	/*
	Projection Matrix should be:
	I * Frustrum * (Orient Z up) * (Orient Camera) * (Move Camera)
	\            Turn screen space into world space             /
	*/
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glFrustum(-4 * aspectRatio, 4 * aspectRatio, -4, 4, 8, 1024);
	glRotated(90,-1,0,0); 
	const vect campos = camera->getPosition();
	glMultMatrixd(camera->getOrientation().toMatrix().inverse()); 
	glTranslated(-campos.x, -campos.y, -campos.z);
	
	// everything else is model matrix
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

//	glTranslated(0, 0, -64);
//	glutWireCube(16);

	world->draw();
}

void WorldApp::keyboard(const unsigned char key) {
	//std::cout << "Key action:" << int(key) << std::endl;

	// due to shitty libraries and requirements
	if (specialPressed(key, GLUT_KEY_UP)) { camera->setOrientation(quat(0,0.1,0,0).calculateW() * camera->getOrientation()); }
	if (specialPressed(key, GLUT_KEY_DOWN)) { camera->setOrientation(quat(0,-0.1,0,0).calculateW() * camera->getOrientation()); }
	if (specialPressed(key, GLUT_KEY_LEFT)) { camera->setOrientation(quat(0,0,0,0.1).calculateW() * camera->getOrientation()); }
	if (specialPressed(key, GLUT_KEY_RIGHT)) { camera->setOrientation(quat(0,0,0,-0.1).calculateW() * camera->getOrientation()); }

	if ((key == '1') && keyPressed('1')) { camera->setTarget(world->getEntities()->find("ghost1")); }
	if ((key == '2') && keyPressed('2')) { camera->setTarget(world->getEntities()->find("ghost2")); }
	if ((key == '3') && keyPressed('3')) { camera->setTarget(world->getEntities()->find("ghost3")); }
	if ((key == '4') && keyPressed('4')) { camera->setTarget(world->getEntities()->find("ghost4")); }
	if ((key == '5') && keyPressed('5')) { camera->setTarget(world->getEntities()->find("pacman")); }
	if ((key == '0') && keyPressed('0')) { camera->setTarget(/*NULL*/0); }
}

void WorldApp::mouse(const int, const int, const int, const int) {

}

void WorldApp::idle() {

}

void WorldApp::timer() {

	if (keyPressed(27)) {
		exit(0);
	}

	if (keyPressed('w')) {
		camera->setPosition(camera->getPosition() + camera->getOrientation().rotate(vect::FORWARD));
	}
	if (keyPressed('s')) {
		camera->setPosition(camera->getPosition() + camera->getOrientation().rotate(vect::BACKWARD));
	}
	if (keyPressed('a')) {
		camera->setPosition(camera->getPosition() + camera->getOrientation().rotate(vect::LEFT));
	}
	if (keyPressed('d')) {
		camera->setPosition(camera->getPosition() + camera->getOrientation().rotate(vect::RIGHT));
	}
	if (keyPressed('x')) {
		camera->setPosition(camera->getPosition() + camera->getOrientation().rotate(vect::UP));
	}
	if (keyPressed('z')) {
		camera->setPosition(camera->getPosition() + camera->getOrientation().rotate(vect::DOWN));
	}

	// TODO: keyvaules
	// rotation
	if (keyPressed('i')) { camera->setOrientation(quat(0,0.02,0,0).calculateW() * camera->getOrientation()); }
	if (keyPressed('k')) { camera->setOrientation(quat(0,-0.02,0,0).calculateW() * camera->getOrientation()); }
	if (keyPressed('q')) { camera->setOrientation(quat(0,0,0.02,0).calculateW() * camera->getOrientation()); }
	if (keyPressed('e')) { camera->setOrientation(quat(0,0,-0.02,0).calculateW() * camera->getOrientation()); }
	if (keyPressed('j')) { camera->setOrientation(quat(0,0,0,0.02).calculateW() * camera->getOrientation()); }
	if (keyPressed('l')) { camera->setOrientation(quat(0,0,0,-0.02).calculateW() * camera->getOrientation()); }

	if (keyPressed('r')) {
		camera->setPosition(vect::ZERO);
		camera->setOrientation(quat::IDENTITY);
	}

	world->think();	
}
